﻿#region Using's

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TestDomainModel;
using LightPersist;

#endregion

namespace LightPersistTests
{
	[TestClass]
	public class NotifyUI_simple_property : ContextTestsBase
	{
		int firedCount;
		string firedPropertyChanged;

		[TestInitialize]
		public void Check_notify_property_init()
		{
			ChangeTransaction();
			ResetFiredCount();
			child.PropertyChanged += (s, e) =>
			{
				if(e.PropertyName == "IsReadonly" || e.PropertyName.StartsWith("__"))
				{
					return;
				}
				firedPropertyChanged = e.PropertyName;
				Console.WriteLine(firedPropertyChanged);
				firedCount++;
			};
		}

		void ResetFiredCount()
		{
			firedCount = 0;
			firedPropertyChanged = null;
		}

		[TestMethod]
		public void Should_provide_interface()
		{
			Assert.IsTrue(child is INotifyPropertyChanged);
		}

		[TestMethod]
		public void Should_not_fire_on_subscribe()
		{
			Assert.AreEqual(0, firedCount, "should not fire on subscribe");
			Assert.IsNull(firedPropertyChanged, "should not fire on subscribe");
		}

		[TestMethod]
		public void Should_notify_changing_of_simple_property()
		{
			child.Width = 2;

			Assert.AreEqual(0, firedCount, "should not fire inside transaction");
			Assert.IsNull(firedPropertyChanged, "should not fire inside transaction");

			tr.CommitTransaction();

			Assert.AreEqual(1, firedCount, "should fire once after commit transaction");
			Assert.AreEqual("Width", firedPropertyChanged, "should fire after commit");
		}

		[TestMethod]
		public void Should_fire_only_once_even_on_multiply_changes()
		{
			child.Width = 2;
			child.Width = 3;
			child.Width = 4;

			Assert.AreEqual(0, firedCount, "should not fire inside transaction");
			Assert.IsNull(firedPropertyChanged, "should not fire inside transaction");

			tr.CommitTransaction();

			Assert.AreEqual(1, firedCount, "should fire once after commit transaction");
			Assert.AreEqual("Width", firedPropertyChanged, "should fire after commit");
		}

		[TestMethod]
		public void Should_not_fire_when_last_new_value_equals_to_initial()
		{
			var init = child.Width;
			child.Width = 2;
			child.Width = 3;
			child.Width = init;

			tr.CommitTransaction();

			Assert.AreEqual(0, firedCount);
			Assert.IsNull(firedPropertyChanged);
		}

		[TestMethod]
		public void Should_not_notify_on_rollback()
		{
			child.Width = 2;
			Context.RollbackTransaction(tr);
			Assert.AreEqual(0, firedCount);
			Assert.IsNull(firedPropertyChanged);
		}

		[TestMethod]
		public void Should_fire_on_single_item_lists_property_changes()
		{
			child.Content = Context.Create<FakeControl>();
			tr.CommitTransaction();
			Assert.AreEqual(1, firedCount);
			Assert.AreEqual("Content", firedPropertyChanged);
		}

		[TestMethod]
		public void Should_not_fire_list_property_changes()
		{
			// becouse lists does not replaced, it is readonly. Only list content are chaneged
			child.Children.Add(Context.Create<FakeControl>());
			tr.CommitTransaction();
			Assert.AreEqual(0, firedCount);
			Assert.IsNull(firedPropertyChanged);
		}

		[TestMethod]
		public void Should_inform_on_resetting_to_null()
		{
			child.Content = Context.Create<FakeControl>();
			ChangeTransaction();
			ResetFiredCount();
			child.Content = null;
			tr.CommitTransaction();
			Assert.AreEqual(1, firedCount);
			Assert.AreEqual("Content", firedPropertyChanged);
		}

		[TestMethod]
		public void Should_report_intermediate_propery_states_beetween_notification()
		{
			//child.
			Assert.Inconclusive();
		}
	}
}